<?php

namespace PhpYes\Apps;

use PhpYes\Com\Router;
use PhpYes\Com\WgxRequest;
use PhpYes\Yes;

/**
 * 通用说明:
 *
 * 1. 本类中 没有使用 final 修饰的 public 和 protected 成员方法 都是 子类可以重写的.
 *
 */
abstract class BaseApp extends BaseConfigApp
{
    const KEY_ROUTER = 'router';
    const KEY_RENDER = 'render';

    /**
     * @return string[]
     */
    public function config_spec_files()
    {
        return [$this->config_file(), $this->config_route_file()];
    }

    /**
     * @return string
     */
    abstract public function config_route_file();

    /**
     * @return array
     */
    public function config_route()
    {
        return $this->config_spec($this->config_route_file());
    }

    /**
     * Router 或者 其子类
     * @return Router
     */
    public function router()
    {
        if (empty(Yes::$kv[self::KEY_ROUTER])) {
            Yes::$kv[self::KEY_ROUTER] = new Router();
        }
        return Yes::$kv[self::KEY_ROUTER];
    }

    /**
     * WgxRequest 或者 其子类
     * @return WgxRequest
     */
    public function getRequest()
    {
        return Yes::getSingle(WgxRequest::class);
    }

    /**
     * absolute view file path, 获取 $view 的 绝对路径
     * 非本库需要的接口函数，具体逻辑由实现决定，所以本库不应该使用这个函数 !!!
     * 例如：项目的 view file 可能存放在 view 目录中，也可能存放在 views 目录中，还可能由其它库提供，
     * 实现可能要求 $view 传递 index.html.php，或者 /index.html.php，或者 index，
     * 亦或者 const PAGE_INDEX, PAGE_ERROR, VIEW_INDEX, VIEW_ERROR 这样的昵称,别名,简称 等等，
     * 实现可能在 A 目录下查找，如果没有找到就 报错 或者 再去 B 目录下查找 等等，
     * 总之，本库 不应该对实现做任何假设，一切具体逻辑都由实现决定，本库不应该使用这个函数 !!!
     *
     * 本 虚函数 的作用是要求 实现者 实现一个这样的函数，以便基于实现的逻辑可以 最大程度 的 统一 和 方便 !!!
     * 实践表明：如果没有一个这样的函数，项目中可能定义多个类似的函数，名称五花八门，
     * 很多需要 $view 绝对路径的地方采用路径拼接:
     * App::$p->getViewDir() . '/index.html.php',
     * App::$p->home_dir() . '/views/index.html.php',
     * App::$p->base_dir() . '/views/index.html.php',
     * BASE_DIR . '/views/index.html.php',
     * 很明显，这样做 既不方便 也不统一
     *
     * 但是，如果这里将逻辑确定下来 并 要求所有地方都这样用，同时以此实现本库中的逻辑，这样做也是不合适的，
     * 例如 管理后台，如果 两个或者多个 项目使用 相同的管理后台 模板，那么其实很多页面和逻辑都是可以共用的，
     * 这时最好是将这些可以共用的部分抽成库，然后这个库供这些项目使用，否则，若是使用拷贝的话，那么修改时就非常麻烦，
     * 使用库的话，那么 $view 就 即存在于项目中，也存在于库中，所以如果这里将逻辑定死下来也不合适
     *
     * @param string $view
     * @return string
     */
    abstract public function absoluteView($view);

    /**
     * Render 或者 其子类
     * @return \PhpYes\Com\Render
     */
    abstract public function render();

}